// ScaffoldingProject.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <fstream>
#include <vector>
#include "Graph.h"
#include <memory>

using namespace GraphTools;


int str2int (const char* str, const int def, const string error) 
{
	int i;
	if(sscanf_s(str, "%d", &i)  == EOF )
	{
		cout << "error in " << error << " value, using default = "<< def <<"\n";
	}
	return i;
}

int main(int argc, char* argv[])
{
	int weight_threshold = 5, percentage_threshold = 40, repeat_treshold = 3;
#if FAST
	string f_name = "primo_giro.txt"; 
#else
	string f_name;// = "10kb_graph.all.txt";
#endif
	fstream file_in;

	cout << "Scaffolding using 2/3 approsimation.\n";
	cout << "Developed by:\n";
	cout << "\tAbbadi Mohamed\n";
	cout << "\tSteffinlongo Enrico\n\n\n";

	if (argc > 1)
	{
		f_name = argv[1];
	}
	else
	{
		cout << "error: Missing input file" << argc;
		return EXIT_FAILURE;
	}
	file_in = fstream(f_name, ios::in);
	if (file_in == NULL)
	{
			cout << "input file doesn't exist\n" << argv[0];	
			return EXIT_FAILURE;
	}
	else
	{
		cout << "Opened " << f_name << " succesfully\n";
	}

	if (argc > 2)
	{
		weight_threshold = str2int(argv[2], 5, "weight threshold");
	}
	else
	{
		cout << "Missing weight threshold value. Using default = 5\n";
	}
	if (argc > 3)
	{
		repeat_treshold = str2int(argv[3], 3, "repeat threshold");
	}	
	else
	{
		cout << "Missing repetition threshold value. Using default = 3\n";
	}
	if (argc > 4)
	{
		percentage_threshold = str2int(argv[4], 40, "percentage threshold");
	}
	else
	{
		cout << "Missing percentage threshold value. Using default = 40\n";
	}

	cout << "\n";
	fstream file_out("out_removed_" + f_name,ios::out);

	map<string, string> filtered = map<string, string>();
	
	Graph initial = Graph(repeat_treshold);

	while (!file_in.eof())
	{
		string v1, v2;
		int weight;
		file_in >> v1 >> v2 >> weight;

		if (weight <= weight_threshold)
		{
			filtered[v1] = v1;
			filtered[v2] = v2;
			continue;
		}

		if (v1 == "" || v2 == "")
		{
			continue;
		}

		initial.AddEdge(v1, v2, weight);
	}

	{
		cout << "Graph builded. Imported " << initial.GetVertices().size() << " nodes\n";
	}

	//for (auto ite = mp.begin(); ite != mp.end(); ++ite)
	//{
	//	cout << ite->first << endl;
	//}

	//cout << "differences " << (vin.size()) - mp.size() << endl;

	//auto vs = initial.GetVertices();
	//int i = 0;
	//{
	//	auto vs = initial.GetVertices();
	//	file_out << "removed becausa unreachable due edge treshold\n";

	//	for (auto ite = filtered.begin(); ite != filtered.end(); ite++)
	//	{
	//		if (vs.find(ite->first) == vs.end())
	//		{
	//			file_out << ite->first << endl;
	//			//write in the file
	//		}
	//	}
	//}

	//initial.ValidateGraph();

	//initial.BreadthFirstVisit();

	initial.RemoveIsolatedNodes();

	//initial.BreadthFirstVisit();

	//cout << "removing repetitions \n";
	{
		auto removed = initial.RemoveRepetitions(percentage_threshold);
		file_out << removed;
		file_out.close();
		cout << "Removed and isolated nodes saved in out_removed_" << f_name << "\n";
		//initial.ValidateGraph();
	}

	//{
	//	auto vs = initial.GetVertices();
	//	file_out << "removed becaus unreachable due edge treshold\n";

	//	for (auto ite = filtered.begin(); ite != filtered.end(); ++ite)
	//	{
	//		if (vs.find(ite->first) == vs.end())
	//		{
	//			file_out << ite->first << endl;
	//			//write in the file
	//		}
	//	}
	//}

	//initial.BreadthFirstVisit();

	initial.ReduceEdges();

	initial.CreateScaffolds();

	fstream scaffold_file_out("scaffolds_" + f_name,ios::out);

	{
		auto scaffolds = initial.GetScaffolds();

		cout << "Found " << scaffolds.size() << " scaffolds\n";

		for (auto ite = scaffolds.begin(); ite != scaffolds.end(); ++ite)
		{
			scaffold_file_out << (*ite)->ToString();
		}
		scaffold_file_out.close();
		cout << "Scaffolds saved in scaffolds_" << f_name << "\n";
	}

	cout << "\n";

	//cout << "destroying\n";

	//system("PAUSE");

	//initial.Destroy();

	system("PAUSE");

	return 0;
}

